package com.cloudkinto.service.material.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.bo.material.MaterialAddBo;
import com.cloudkinto.bo.material.MaterialQueryBo;
import com.cloudkinto.bo.material.MaterialUpdateBo;
import com.cloudkinto.common.BeanConvert;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.StringsUtil;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.dao.MaterialDao;
import com.cloudkinto.dao.OrderOutboundPackageMaterialDao;
import com.cloudkinto.dao.ProductDao;
import com.cloudkinto.entity.MaterialDo;
import com.cloudkinto.entity.OrderOutboundPackageMaterialDo;
import com.cloudkinto.entity.ProductDo;
import com.cloudkinto.service.material.MaterialService;
import com.cloudkinto.vo.common.CommonBatchOperationVo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 包材 service实现类
 * </p>
 *
 * @author long
 * @since 2024-12-03
 */
@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor
public class MaterialServiceImpl extends ServiceImpl<MaterialDao, MaterialDo> implements MaterialService {

    private final OrderOutboundPackageMaterialDao outboundPackageMaterialDao;

    private final ProductDao productDao;

    @Override
    public void add(MaterialAddBo req) {
//        MaterialDo entityDo = new MaterialDo();
//        BeanUtils.copyProperties(req, entityDo);
        MaterialDo entityDo = BeanConvert.INSTANCE.materialAddBoToMaterialDo(req);
        MaterialDo exist = baseMapper.selectOne(Wrappers.<MaterialDo>lambdaQuery().eq(MaterialDo::getMaterialCode, req.getMaterialCode()).last(" limit 1"));
        if (Objects.nonNull(exist)) {
            throw new BizException(SysConstant.Material_Code_Exists, req.getMaterialCode());
        }
        baseMapper.insert(entityDo);
    }

    @Override
    public void update(MaterialUpdateBo req) {
        MaterialDo entityDo = baseMapper.selectById(req.getId());
//        BeanUtils.copyProperties(req, entityDo);
        BeanConvert.INSTANCE.materialUpdateBoToMaterialDo(req, entityDo);
        baseMapper.updateById(entityDo);
    }

    @Override
    public CommonBatchOperationVo delete(Long id) {
        CommonBatchOperationVo res = new CommonBatchOperationVo();
        res.setTotal(1);
        MaterialDo materialDo = baseMapper.selectById(id);
        List<ProductDo> productDoList = productDao.getListByWhIdAndPackCode(materialDo.getWhId(), materialDo.getMaterialCode());
        if (CollUtil.isNotEmpty(productDoList)) {
            HashMap<String, Object> map = new HashMap<>(4);
            map.put("code", materialDo.getMaterialCode());
            map.put("errorMsg", StringsUtil.createI18Message(SysConstant.Product_Using_Delete_Failed));
            res.getFailedList().add(map);
            res.setFailed(res.getFailed() + 1);
            return res;
        }
        List<OrderOutboundPackageMaterialDo> packageMaterialDoList = outboundPackageMaterialDao.selectList(
                Wrappers.<OrderOutboundPackageMaterialDo>lambdaQuery()
                        .eq(OrderOutboundPackageMaterialDo::getMaterialCode, materialDo.getMaterialCode())
        );
        if (CollUtil.isNotEmpty(packageMaterialDoList)) {
            HashMap<String, Object> map = new HashMap<>(4);
            map.put("code", materialDo.getMaterialCode());
            map.put("errorMsg", StringsUtil.createI18Message(SysConstant.Outbound_Using_Delete_Failed));
            res.getFailedList().add(map);
            res.setFailed(res.getFailed() + 1);
            return res;
        }
        baseMapper.deleteById(id);
        res.setSuccess(res.getSuccess() + 1);
        return res;
    }

    @Override
    public MaterialDo detail(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    public PageResult getListPage(MaterialQueryBo bo) {
        IPage<MaterialDo> page = new Page<>(bo.getCurrent(), bo.getPageSize());
        page = this.page(page, this.queryBuild(bo));
        return new PageResult<>(page.getRecords(), (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
    }

    private LambdaQueryWrapper<MaterialDo> queryBuild(MaterialQueryBo bo) {
        LambdaQueryWrapper<MaterialDo> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(bo.getMaterialCode()), MaterialDo::getMaterialCode, bo.getMaterialCode());
        lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), MaterialDo::getMaterialName, bo.getMaterialName());
        lqw.eq(Objects.nonNull(bo.getTenantId()), MaterialDo::getTenantId, bo.getTenantId());
        lqw.eq(Objects.nonNull(bo.getWhId()), MaterialDo::getWhId, bo.getWhId());
        if (StrUtil.isNotBlank(bo.getSortName())) {
            lqw.last("order by " + bo.getSortName() + "," + "id " + bo.getSortOrder());
        } else {
            lqw.orderByDesc(MaterialDo::getUpdateTime, MaterialDo::getId);
        }
        return lqw;
    }
}
